// 
// Copyright (c) 2006-2009 Ben Motmans
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// Author(s):
//    Ben Motmans <ben.motmans@gmail.com>
//

using System;
using System.Collections.Generic;

namespace Anculus.Core
{
	/// <summary>
	/// Container class for <see cref="ISetSearchAlgorithm"/> search results.
	/// </summary>
	public struct SearchResult : IEquatable<SearchResult>
	{
		/// <summary>
		/// 
		/// </summary>
		public static readonly SearchResult Empty = new SearchResult (-1, null);

		/// <summary>
		/// Initializes a new instance of the <see cref="SearchResult"/> struct.
		/// </summary>
		/// <param name="index">The index.</param>
		/// <param name="match">The match.</param>
		internal SearchResult (int index, string match)
			: this ()
		{
			Index = index;
			Match = match;
		}

		/// <summary>
		/// Gets the index.
		/// </summary>
		/// <value>The index.</value>
		public int Index { get; internal set; }

		/// <summary>
		/// Gets the length of the Matched keyword.
		/// </summary>
		/// <value>The length.</value>
		public int Length { get; internal set; }

		/// <summary>
		/// Gets the matched keyword.
		/// </summary>
		/// <value>The matched keyword.</value>
		public string Match { get; internal set; }

		/// <summary>
		/// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
		/// </summary>
		/// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
		/// <returns>
		/// 	<c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
		/// </returns>
		public override bool Equals (object obj)
		{
			if (obj == null)
				return false;
			
			SearchResult sr = (SearchResult)obj;
			return Index == sr.Index && Match == sr.Match;
		}

		public bool Equals (SearchResult other)
		{
			return Index == other.Index && Match == other.Match;
		}

		/// <summary>
		/// Returns a hash code for this instance.
		/// </summary>
		/// <returns>
		/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
		/// </returns>
		public override int GetHashCode ()
		{
			return Index.GetHashCode () ^ Match.GetHashCode ();
		}

		/// <summary>
		/// Implements the operator ==.
		/// </summary>
		/// <param name="sr1">A SearchResult.</param>
		/// <param name="sr2">A SearchResult.</param>
		/// <returns>The result of the comparison.</returns>
		public static bool operator == (SearchResult sr1, SearchResult sr2)
		{
			return sr1.Index == sr2.Index && sr1.Match == sr2.Match;
		}

		/// <summary>
		/// Implements the operator !=.
		/// </summary>
		/// <param name="sr1">A SearchResult.</param>
		/// <param name="sr2">A SearchResult.</param>
		/// <returns>The result of the comparison.</returns>
		public static bool operator != (SearchResult sr1, SearchResult sr2)
		{
			return sr1.Index != sr2.Index || sr1.Match != sr2.Match;
		}
	}

	/// <summary>
	/// Comparer class to compare <see cref="SearchResult"/>
	/// </summary>
	public sealed class SearchResultComparer : IPropertyComparer<SearchResult, int>, IComparer<SearchResult>
	{
		/// <summary>
		/// Compares the specified SearchResult with an index.
		/// </summary>
		/// <param name="sr">The SearchResult.</param>
		/// <param name="index">The index.</param>
		/// <returns>TODO</returns>
		public int Compare (SearchResult sr, int index)
		{
			return sr.Index.CompareTo (index);
		}

		/// <summary>
		/// Compares the specified SearchResults.
		/// </summary>
		/// <param name="sr1">A SearchResult.</param>
		/// <param name="sr2">A SearchResult.</param>
		/// <returns>TODO</returns>
		public int Compare (SearchResult sr1, SearchResult sr2)
		{
			return sr1.Index.CompareTo (sr2.Index);
		}
	}
}
